We are migrating the bug tracker to github Issues. This is now the preferred way to report NASM bugs.

Self-registration is disabled due to spam issue (mail gorcunov@gmail.com or hpa@zytor.com to create an account)

Bug 3392909 - Intended for -O1 to make all unmarked conditional jumps near?
Summary: Intended for -O1 to make all unmarked conditional jumps near?
Status: CLOSED INVALID
Alias: None
Product: NASM
Classification: Unclassified
Component: Assembler (show other bugs)
Version: 3.00.xx
Hardware: All All
: Medium annoyance
Assignee: nobody
URL:
Depends on:
Blocks:
 
Reported: 2024-03-18 16:56 PDT by E. C. Masloch
Modified: 2024-04-12 11:09 PDT (History)
4 users (show)

Obtained from: Built from git using configure
Generated by: Human
Bug category: Unexpected or confusing behavior
Observed for: Invalid input
Regression: ---
Regression since:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description E. C. Masloch 2024-03-18 16:56:29 PDT
The -O1 parameter seems useless and like it shouldn't be used because any conditional jump (except jcxz and loop*) that isn't explicitly marked "short" expands to a near conditional jump. With a "cpu 8086" directive the two-instruction workaround is used, with "cpu 386" the 386 single-instruction near jump is used.

Test case:

test$ cat test.asm

%ifdef CPU
        cpu CPU
%endif

backward:
        je backward
        jcxz backward

        jcxz forward
        jne forward
forward:

test$ nasm -v
NASM version 2.16.02rc2 compiled on Oct 12 2023
test$ nasm test.asm -l /dev/stderr -O1 -DCPU=8086
     1
     2                                  %ifdef CPU
     3                                          cpu CPU
     4                                  %endif
     5
     6                                  backward:
     7 00000000 7503E9FBFF                      je backward
     8 00000005 E3F9                            jcxz backward
     9
    10 00000007 E305                            jcxz forward
    11 00000009 7403E90000                      jne forward
    12                                  forward:
    13
test$ nasm test.asm -l /dev/stderr -O1 -DCPU=386
     1
     2                                  %ifdef CPU
     3                                          cpu CPU
     4                                  %endif
     5
     6                                  backward:
     7 00000000 0F84FCFF                        je backward
     8 00000004 E3FA                            jcxz backward
     9
    10 00000006 E304                            jcxz forward
    11 00000008 0F850000                        jne forward
    12                                  forward:
    13
test$

In the manual it is documented that it should work like this: https://www.nasm.us/xdoc/2.16.01/html/nasmdoc2.html#section-2.1.24

> -O1: Minimal optimization. As above, but immediate operands which will fit in a signed byte are optimized, unless the long form is specified. Conditional jumps default to the long form unless otherwise specified.

This wording was added in https://github.com/netwide-assembler/nasm/commit/dc0bf47feb96884d658d0eceba8ce669c81cf591

This is a bug in that we expect -O1 to optimise more than -O0, not to pessimise the code. If the behaviour is not changed I would advice at least adding a bigger disclaimer that -O1 is often worse than -O0.
Comment 1 H. Peter Anvin 2024-04-12 10:53:46 PDT
This is intended, and has been the behavior ever since the multipass optimizer was introduced, and it has been requested that we do not change it, as the (few) users who have it want explicitly predictable output (mostly for testing.)

This is documented.

In fact, specifying *any* -O option will generate worse (or equal) code, since -Ox is the default.
Comment 2 H. Peter Anvin 2024-04-12 11:09:45 PDT
I have added a stronger note to the documentation for this.